Các cấu trúc dòng điều khiển Cú pháp ngôn ngữ C

Một cách cơ bản thì C là ngôn ngữ dạng tự do. Trong phần này, tất cả các chữ "mệnh đề" có nghĩa tương đương với chữ "câu lệnh".

Các mệnh đề phức hợp

Câu lệnh phức hợp được bọc trong dấu ngoặc {} còn được gọi là khối mã. Các câu lệnh phức hợp trong C có dạng.

{ <danh sách khai báo tùy chọn> <danh sách câu lệnh tùy chọn> }

Khối mã được dùng như là phần thân của một hàm hay đưọc đặt bất kì ở vị trí nào mà một câu lệnh đơn giản có thể đặt. Nghĩa là, về ý nghĩa văn phạm thì câu lệnh đơn giản và câu lệnh phức hợp là tương đương nhau.

Các mệnh đề biểu thức

Một câu lệnh (hay một mệnh đề) của C có dạng:

<biểu thức tùy chọn>;

là một mệnh đề biểu thức. Nếu biểu thức này không có nội dung (mà chỉ còn lại dấu ; thì biểu thức được gọi là mệnh đề null (hay mệnh dề rỗng). (Theo ngôn ngữ máy Assembler thì mệnh đề null sẽ tương đương với câu lệnh NOP; chiếm 1 byte chỉ làm nhiệm vụ tăng địa chỉ của chồng (stack) lên 1 đơn vị.)

Các mệnh đề lựa chọn (hay điều kiện)

Có ba loại mệnh đề lựa chọn: hai loại dùng từ khóa if và một loại dùng từ khóa switch. Đó là:

Dạng dùng từ khóa if

if (<biểu thức>)<mệnh đề1>;
if (<biểu thức>)<mệnh đề1>;else<mệnh đề2>;

Trong dạng này, nếu phần trong ngoặc đơn có giá trị khác 0 hay có giá trị "đúng" (true) thì dòng điều khiển sẽ chuyển vào để thực thi <mệnh đề1>. Nếu trong câu lệnh if có thêm từ khóa else thì <mệnh đề2> sẽ được thực thi một khi <biểu thức> có giá trị 0 hay giá trị "sai".

Nhắc lại: như trên thì vị trí mỗi mệnh đề đều có thể thay bằng một khối mã.

Trong cách viết mã lồng nhau phức tạp bao gồm nhiều mệnh đề if thì từ khóa else sẽ được gán vào mệnh đề if phía trên gần nhất nào chưa được ghép. Để tránh sự nhầm lẫn cách tốt nhất là lồng chúng vào trong các dấu {}.

Dạng dùng từ khóa switch

Mệnh đề switch sẽ gây ra việc chuyển dòng điều khiển sang một trong những mệnh đề con kế tiếp tùy theo giá trị của một biểu thức X (biểu thức này phải có kiểu nguyên). Các mệnh đề con này thường là các mệnh đề phức hợp. Đứng trước mỗi mệnh đề con sẽ là một từ khóa case, sau đó là một biểu thức hằng Hi, và dấu hai chấm : gắn liền tiếp theo đó là mệnh đề con Mi.

Khi giá trị của X trùng với một giá trị Hi được nêu ở đâu thì mệnh đề con đi gắn liền với hằng tại đó (tức là Mi) sẽ được thực thi.

Nếu X không bằng với bất kì giá trị Hi nào thì người lập trình có thể dùng thêm từ khóa default, sau đó là dấu hai chấm : và tiếp theo là một mệnh đề con Mdefault. Mệnh đề con này sẽ được thực thi khi mà giá trị của X khác với mọi giá trị hằng Hi.

Lưu ý:

  • Trong câu lệnh switch thì không cho phép có hai giá trị hằng bằng nhau. Nghĩa là khi X được đánh giá thì chỉ có tối đa một mệnh đề con được thực thi.
  • Các câu lệnh switch có thể được dùng trong dạng lồng vào nhau (nest), một từ khóa case hay default sẽ thuộc vào câu lệnh switch bên trong nhất (hay nhỏ nhất) chứa nó.
  • Một khi dòng điều khiển hoàn tất câu lệnh con Mi thì nó sẽ tiếp tục thi hành các câu lệnh con Mi+1 theo sau cho đến khi nó bị yêu cầu ngưng bởi câu lệnh nhảy (mà thường dược dùng nhiều nhất là câu lệnh break)

Trong dạng thí dụ dưới đây, nếu <biểu thức X> có giá trị bằng <hằng H2> thì mệnh đề các biểu thức <mệnh đề M2>,<mệnh đề M3>, và <mệnh đề Mdefault> sẽ lần lần lượt được thực thi theo thứ tự nếu như trong chúng không có câu lệnh break. Nhưng vì trong mã thí dụ có câu lệnh break nên dòng điều khiển sẽ ngưng và kết thúc câu lệnh switch khi thi hành lệnh break này.

switch (<biểu thức X>){case <hằng H1>: 
<mệnh đề M1>
case <hằng H2>:
<mệnh đề M2>
break;
case <hằng H3>:
<mệnh đề M3>
default:
<mệnh đề Mdefault>
}

Các mệnh đề tái lặp (hay vòng lặp)

C có 3 dạng câu lệnh vòng lặp:

Vòng lặp do

do<mệnh đề>while (<biểu thức>);

Trong mệnh đề này thì mệnh đề được thực thi lặp lại cho tới khi nào <biểu thức> được đánh giá (hay có giá trị) là true. Một khi <biểu thức> không còn có giá trị true nữa thì vòng lặp sẽ bị kết thúc.

Vòng lặp while

while (<biểu thức>)<mệnh đề>

<mệnh đề> chỉ được thực thi hay thực thi lặp lại khi <biểu thức> có giá trị là true. Nếu <biểu thức> có giá trị false thì câu lệnh sẽ bị kết thúc ngay lập tức.

Vòng lặp for

Dạng C89 của vòng lặp for là:

for (<biểu thức 1>; <biểu thức 2>; <biểu thức 3>)<câu lệnh>

Nó đã được tổng quát hóa trong C99 thành:

for (<khai báo> <biểu thức 1>; <biểu thức 2>)<câu lệnh>

Khi cả ba biểu thức đều hiện diện trong một câu lệnh for, thì mệnh đề:

for (e1; e2; e3)s;

sẽ tương đương với

e1;while (e2) {s;e3;}

Bất kì biểu thức nào trong vòng lặp for có thể được loại bỏ. Một biểu thức bị mất (e2 chẳng hạn) có thể làm cho vòng lặp biến thành vòng lặp vô hạn.

Thí dụ: vòng lặp for sau đây 3 biểu thức ở dạng phức hợp và ngăn cách nhau bởi dấu chấm phẩy ;:
for (x=10,y=1;((x>4) && (y<8)); x--,y+=2) printf("x = %d, y = %d \n", x,y);

Kết quả thực thi màn hình sẽ hiển thị như sau:

x = 10, y = 1x = 9, y = 3x = 8, y = 5x = 7, y = 7

Vòng lặp kết thúc vì điều kiện trong biểu thức thứ nhì ((x>4) && (y<8)) không còn đúng nữa.

Các mệnh đề nhảy (hay bước nhảy)

Các lệnh nhảy sẽ thay đổi dòng điều khiển một cách vô điều kiện. có 4 kiểu mệnh đề nhảy trong C là goto, continue, break, và return.

goto

câu lệnh goto sẽ có dạng:

goto <nhãn>;

nhãn phải có mặt trong hàm có chứa câu lệnh goto. Khi đọc đến lệnh này, dòng điều khiển sẽ chuyển đến mệnh đề nhãn.

continue

Mệnh đề continue chỉ có thể xuất hiện trong một vòng lặp và có tác dụng làm cho dòng điều khiển chuyển sang chu kì mới của vòng lặp trong cùng nhất (có chứa câu lệnh). Các dạng sử dụng bao gồm

while (expression) {/*... */cont:;}
do {/*... */cont:;} while (expression);
for (optional-expr; optexp2; optexp3) {/*... */cont:;}

break

Mệnh đề break dùng để kết thúc một câu lệnh vòng lặp hay câu lệnh switch ngay lập tức và chuyển tiếp đến câu lệnh tiếp theo sau của vòng lặp đó.

return

Một hàm trả dòng điều khiển về nơi gọi nó bằng câu lệnh return. Khi lệnh return được theo sau bởi một biểu thức thì biểu thức đó sẽ được đánh giá và giá trị này sẽ được trả về cho nơi đã gọi hàm. Khi return được gọi mà không có biểu thức đi kèm thì giá trị trả về là không xác định.